package HslCommunication;

import HslCommunication.Core.Net.IReadWriteNet;
import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.yhy.wxzn.wcs.device.netty.bean.ResultData;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.nio.charset.Charset;

/**
 * 西门子驱动帮助类
 */
@Slf4j
public class SiemensHelper {
    private SiemensPLCS siemensPLCS;
    private SiemensS7Net siemensS7Net;
    private OperateResult connect;
    private IReadWriteNet readWriteNet;
    private Method readByteMethod;
    private Method writeByteMethod;
    private byte plc_rack;
    private byte plc_slot;
    private volatile boolean connected;
    private final int plcPort;
    private String plcIP;

    public SiemensHelper(int type, byte plc_rack, byte plc_slot) {
        this.siemensPLCS = SiemensPLCS.S1200;
        this.readByteMethod = null;
        this.writeByteMethod = null;
        this.plcPort = 102;
        this.plcIP = "127.0.0.1";
        this.siemensPLCS = getS7PlcType(type);
        this.plc_rack = plc_rack;
        this.plc_slot = plc_slot;
        this.siemensS7Net = new SiemensS7Net(this.siemensPLCS);
    }

    private SiemensPLCS getS7PlcType(int type) {
        SiemensPLCS siemensPLCS = null;
        switch (type) {
            case 1:
                siemensPLCS = SiemensPLCS.S1500;
                break;
            case 2:
                siemensPLCS = SiemensPLCS.S1200;
                break;
            case 3:
                siemensPLCS = SiemensPLCS.S400;
                break;
            case 4:
                siemensPLCS = SiemensPLCS.S300;
                break;
            case 5:
                siemensPLCS = SiemensPLCS.S200;
                break;
            case 6:
                siemensPLCS = SiemensPLCS.S200Smart;
                break;
            default:
                siemensPLCS = SiemensPLCS.S1500;
        }
        return siemensPLCS;
    }

    public boolean isConnectd() {
        return this.connected;
    }

    public void closeConn() {
        if (this.siemensS7Net != null) {
            this.siemensS7Net.ConnectClose();
        }
    }

    public void close() {
        this.closeConn();
    }

    public void connect() {
        if (!StringUtil.isNullOrEmpty(this.plcIP)) {
            this.connect(this.plcIP);
        }
    }

    public void connect(String host) {
        if (!this.isConnectd()) {
            this.plcIP = host;

            try {
                this.siemensS7Net.setIpAddress(this.plcIP);
                this.siemensS7Net.setPort(102);
                this.siemensS7Net.setRack(this.plc_rack);
                this.siemensS7Net.setSlot(this.plc_slot);
                this.connect = this.siemensS7Net.ConnectServer();
                if (this.connect.IsSuccess) {
                    this.readWriteNet = this.siemensS7Net;

                    try {
                        this.readByteMethod = this.readWriteNet.getClass().getMethod("ReadByte", String.class);
                    } catch (Exception var4) {
                    }

                    try {
                        this.writeByteMethod = this.readWriteNet.getClass().getMethod("Write", String.class, Byte.TYPE);
                    } catch (Exception var3) {
                    }

                    this.connected = Boolean.TRUE;
                } else {
                    this.connected = Boolean.FALSE;
                    log.error("连接失败=====>{}", this.connect.ToMessageShowString());
                }
            } catch (Exception var5) {
                var5.printStackTrace();
            }

        }
    }

    public ResultData readBool(String address) {
        return this.readBit(address, 1);
    }

    public ResultData readBit(String address, int length) {
        address = getAddress(address);
        ResultData rd = null;
        if (length == 1) {
            rd = this.readResultRender(address, this.readWriteNet.ReadBool(address));
        } else {
            rd = this.readResultRender(address, this.readWriteNet.ReadBool(address, (short) length));
        }

        return rd;
    }

    public ResultData readInt(String address) {
        return this.readInt(address, 1);
    }

    public ResultData readInt(String address, int length) {
        address = getAddress(address);
        ResultData rd = null;
        if (length == 1) {
            rd = this.readResultRender(address, this.readWriteNet.ReadInt32(address));
        } else {
            rd = this.readResultRender(address, this.readWriteNet.ReadInt32(address, (short) length));
        }

        return rd;
    }

    public ResultData readShort(String address) {
        return this.readShort(address, 1);
    }

    public ResultData readShort(String address, int length) {
        address = getAddress(address);
        ResultData rd = null;
        if (length == 1) {
            rd = this.readResultRender(address, this.readWriteNet.ReadInt16(address));
        } else {
            rd = this.readResultRender(address, this.readWriteNet.ReadInt16(address, (short) length));
        }

        return rd;
    }

    public ResultData readString(String address, int length) {
        address = getAddress(address);
        ResultData rd = null;
        rd = this.readResultRender(address, this.readWriteNet.ReadString(address, (short) length));
        return rd;
    }

    public ResultData readString(String address, int length, String encoding) {
        address = getAddress(address);
        ResultData rd = null;
        rd = this.readResultRender(address, this.readWriteNet.ReadString(address, (short) length, Charset.forName(encoding)));
        return rd;
    }

    public ResultData readBytes(String address, int length) {
        address = getAddress(address);
        ResultData rd = null;
        rd = this.readResultRender(address, this.readWriteNet.Read(address, (short) length));
        return rd;
    }

    public ResultData readByte(String address) {
        address = getAddress(address);
        ResultData rd = null;

        try {
            OperateResultExOne<Byte> read = (OperateResultExOne) this.readByteMethod.invoke(this.readWriteNet, address);
            rd = this.readResultRender(address, read);
        } catch (Exception var4) {
            var4.printStackTrace();
        }

        return rd;
    }

    public <T> ResultData readResultRender(String address, OperateResultExOne<T> result) {
        ResultData rd = new ResultData();
        rd.setConnecd(this.isConnectd());
        rd.setMessage("当前与PLC通信断开！");
        rd.setSuccess(result.IsSuccess);
        if (result.IsSuccess) {
            rd.setMessage("读取成功");
            rd.setValue(result.Content);
        } else {
            this.connect.IsSuccess = false;
            this.closeConn();
            rd.setMessage(result.ToMessageShowString());
        }

        this.connected = this.connect.IsSuccess;
        return rd;
    }

    public ResultData writeResultRender(String address, OperateResult result) {
        ResultData rd = new ResultData();
        rd.setConnecd(this.isConnectd());
        rd.setMessage("当前与PLC通信断开！");
        rd.setSuccess(result.IsSuccess);
        if (result.IsSuccess) {
            rd.setMessage("写入成功");
        } else {
            this.connect.IsSuccess = false;
            this.closeConn();
            rd.setMessage(result.ToMessageShowString());
        }

        this.connected = this.connect.IsSuccess;
        return rd;
    }

    public ResultData write(String address, boolean value) {
        return this.writeBit(address, value);
    }

    public ResultData write(String address, short value) {
        return this.writeShort(address, value);
    }

    public ResultData write(String address, int value) {
        return this.writeInt(address, value);
    }

    public ResultData write(String address, byte[] value) {
        return this.writeBytes(address, value);
    }

    public ResultData write(String address, byte value) {
        return this.writeByte(address, value);
    }

    public ResultData writeBit(String address, boolean value) {
        address = getAddress(address);
        ResultData rd = null;
        rd = this.writeResultRender(address, this.readWriteNet.Write(address, value));
        return rd;
    }

    public ResultData writeInt(String address, int value) {
        address = getAddress(address);
        ResultData rd = null;
        rd = this.writeResultRender(address, this.readWriteNet.Write(address, value));
        return rd;
    }

    public ResultData writeString(String address, String value) {
        address = getAddress(address);
        ResultData rd = null;
        rd = this.writeResultRender(address, this.readWriteNet.Write(address, value));
        return rd;
    }

    public ResultData writeString(String address, String value, String encoding) {
        address = getAddress(address);
        ResultData rd = null;
        rd = this.writeResultRender(address, this.readWriteNet.Write(address, value, Charset.forName(encoding)));
        return rd;
    }

    public ResultData writeBytes(String address, byte[] bytes) {
        address = getAddress(address);
        ResultData rd = null;

        try {
            rd = this.writeResultRender(address, this.readWriteNet.Write(address, bytes));
        } catch (Exception var5) {
            log.error("写入byte异常{},{}", address, var5);
        }

        return rd;
    }

    public ResultData writeByte(String address, byte bt) {
        address = getAddress(address);
        ResultData rd = null;

        try {
            OperateResult write = (OperateResult) this.writeByteMethod.invoke(this.readWriteNet, address, bt);
            rd = this.writeResultRender(address, write);
        } catch (Exception var5) {
            log.error("写入byte异常{},{}", address, var5);
        }

        return rd;
    }

    public ResultData writeShort(String address, short value) {
        address = getAddress(address);
        ResultData rd = null;
        rd = this.writeResultRender(address, this.readWriteNet.Write(address, value));
        return rd;
    }

    public static String getAddress(String address) {
        address = address.replace("DBX", "");
        address = address.replace("DBB", "");
        address = address.replace("DBW", "");
        return address;
    }
}
